
using System;
using System.Collections.Generic;
using System.Threading;

using agsXMPP;
using agsXMPP.Xml.Dom;
using agsXMPP.protocol.client;
using agsXMPP.protocol.iq.roster;
using agsXMPP.protocol.extensions.geoloc;

using stefc.geo.platform;
using stefc.geo.lib;

namespace stefc.geo.xmpp
{
	public class XMPPComp : IXMPP
	{
		private XmppClientConnection connection;
		private Jid sender;
		private int pollIntervall;
		
		private volatile Presence presence;
		private volatile bool stop;
		private volatile bool loggedIn;

		public XMPPComp (int pollIntervall)
		{
			this.pollIntervall = pollIntervall;
		}
		
		public void In_Start(string jid, string password)
		{
			this.stop=false;
			this.loggedIn=false;
			
			this.sender = new Jid(jid);
			this.connection = new XmppClientConnection(this.sender.Server);
			
			this.connection.OnError += delegate(object sender, Exception ex) {
				Console.WriteLine("error");
			};
			
			this.connection.OnAuthError += delegate(object sender, agsXMPP.Xml.Dom.Element e) {
				Console.WriteLine("autherror");
			};
			
			this.connection.OnPresence += ProcessStanza;
			
			this.connection.OnLogin += delegate(object o) { 
				this.loggedIn=true;
            };
            
			
			this.connection.Open(this.sender.User, password);
			
			while(!this.stop && !this.loggedIn)
			{
				Thread.Sleep(1000);
			}
			
			while(!this.stop)
			{
				if(this.presence!=null)
				{
					this.connection.Send(this.presence);
				}
				Thread.Sleep(1000*this.pollIntervall);
			}
			
			this.connection.Close();
		}
		
		public void In_Stop()
		{
			this.stop=true;
		}
		
		public void In_Presence(Geographic location)
		{
			this.presence = new Presence();
            this.presence.Priority = this.connection.Priority;
            this.presence.Status = this.connection.Status;
            this.presence.Show = ShowType.chat;
            this.presence.AddChild(new GeoLoc(location.Lat, location.Lon));
		}
		
		public void In_Send(string receiver, string message)
		{
			if(this.loggedIn && (!this.stop))
			{
				this.connection.Send(
					new Message(new Jid(receiver), MessageType.chat, message));
			}
		}
		
		private	void ProcessStanza(object sender, Presence stanza)
		{
			if (!stanza.HasTag(typeof(GeoLoc), true))
				return;

			string user = stanza.From.Bare;
			GeoLoc geoLoc = (GeoLoc)stanza.SelectSingleElement(typeof(GeoLoc));
			Geographic geographic = new Geographic(geoLoc.Latitude,geoLoc.Longitude);
			if(this.Out_Presence!=null)
				this.Out_Presence(new KeyValuePair<string,Geographic>(
				         user,geographic));
		}
		
		public event Action<KeyValuePair<string,Geographic>> Out_Presence;
	}
}
